home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / pick / pick2.c < prev    next >
C/C++ Source or Header  |  1996-11-11  |  22KB  |  823 lines

  1. /*
  2.  * Copyright 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *   pick2.c:  an openGL RGB, double buffered and overlay window example 
  19.  *             program to demonstrate picking in openGL.
  20.  *
  21.  *            - LEFTMOUSE:  move the polygons around a center
  22.  *            - RIGHTMOUSE:  use rubber band to pick polygons 
  23.  *            - Esc key:  exit
  24.  *
  25.  *   By  Philip W. Ho   
  26.  */
  27.  
  28. /* Compile: cc -o pick2 pick2.c -lGL -lGLU -lXext -lX11       */
  29. /* Usage:  pick2 [nx] [ny]                                        */
  30. /*         nx - no. of polygons in x direction 
  31.            ny - no. of polygons in y direction                */
  32.  
  33. #include <GL/glx.h>
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <X11/keysym.h>
  37. #include <X11/Xlib.h>
  38. #include <X11/Xutil.h>
  39.  
  40. #define TRUE            1
  41. #define FALSE           0
  42.  
  43. Display *dpy;                                    /* The X server connection */
  44. Atom del_atom;                                   /* WM_DELETE_WINDOW atom   */
  45. Window glwin, o_win=NULL;                        /* handle to the GL window */
  46. XEvent event;
  47. XWindowAttributes winattri;
  48. unsigned long fore,back;
  49. XGCValues values;
  50. GC  mygc;
  51. long valuemask;
  52.  
  53. GLXContext cx,cx_o;
  54.  
  55. /* Data for polygon */
  56. typedef struct {
  57.    int id;
  58.    float xyz[3];
  59. } Grid;
  60.  
  61. typedef struct {
  62.    int id;
  63.    int type;
  64.    int nd;
  65.    int conn[4];
  66.    int colr;
  67.    float xyz[12];
  68. } Elem;
  69.  
  70.  
  71. int double_buffer = TRUE;
  72.  
  73. XColor green_pixel,green_exact;
  74.  
  75. int no_grid;
  76. int no_elem;
  77. int nx,ny;
  78. int picking;
  79. Elem *elem, *em;
  80. Grid *grid, *gd;
  81.  
  82. #define pick_buffer_size  2000
  83. GLuint  pick_buffer[pick_buffer_size];
  84.  
  85. /* function declarations */
  86.  
  87. static void openwindow(char *);
  88. static void resize_buffer(void);
  89. static void clean_exit(void);
  90. void initGL(void);
  91. void orient(void);
  92. void drawScene(void);
  93. void drawPolys(void);
  94. void DrawXorPolyline(int , XPoint *);
  95. void gendata(int, int);
  96. void reset_color(void );
  97. void open_auxwin(void );
  98. void clearbox(void );
  99. void set_picking(XPoint *);
  100.  
  101. static float objmat[16] = {
  102.          1.0, 0.0, 0.0, 0.0,
  103.          0.0, 1.0, 0.0, 0.0,
  104.          0.0, 0.0, 1.0, 0.0,
  105.          0.0, 0.0, 0.0, 1.0,
  106. };
  107.  
  108. int xsize, ysize;                        /* current size-of-window keepers */
  109. double scrnaspect;                                   /* aspect ratio value */
  110. int xpos, ypos, oxpos, oypos;                /* old and new mouse position */
  111. XPoint box[5];
  112. int  xup1,yup1;
  113. int  xup2,yup2;
  114.  
  115.  
  116. main(argc,argv)
  117. int argc;
  118. char **argv;
  119. {
  120.     int myExpose, myConfigure, myButtPress, myKeyPress;
  121.     int firsttime,myXor;
  122.     int needToDraw = 0;                  /* don't set this to true until
  123.                                             we get our first Expose event */
  124.  
  125.     myExpose = myConfigure = myButtPress = myKeyPress = FALSE;
  126.     myXor = FALSE;
  127.     firsttime = 0;
  128.  
  129.     if(argc == 3)
  130.     {
  131.       nx = atoi(argv[1]);
  132.       ny = atoi(argv[2]);
  133.     }
  134.     else
  135.     {
  136.       nx = 10;
  137.       ny = 10;
  138.     }
  139.  
  140.     openwindow(argv[0]);
  141.  
  142.     gendata(nx,ny);
  143.  
  144.     picking = 0;
  145.  
  146.    /* start out making the singlebuffer window be our current GL window */
  147.     initGL();                                          /* do GL init stuff */
  148.  
  149.     /*
  150.      * The event loop.
  151.      */
  152.     while (1) {         /* standard logic:  get event(s), process event(s) */
  153.  
  154.         XEvent event;
  155.         KeySym keysym;
  156.         char buf[4];
  157.  
  158.     /* this "do while" loop does the `get events' half of the "get events,
  159.      *  process events" action of the infinite while.  this is to ensure
  160.      *  the event queue is always drained before the events that have come
  161.      *  in are processed.
  162.      */
  163.         do {
  164.  
  165.             XNextEvent(dpy, &event);
  166.             switch (event.type) {
  167.  
  168.             /* "Expose" events are sort of like "REDRAW" in gl-speak in
  169.              *  terms of when a window becomes visible, or a previously
  170.              *  invisible part becomes visible.
  171.              */
  172.                 case Expose:                        /* Exposures */
  173.                     needToDraw = myExpose = TRUE;
  174.                     if(o_win == NULL)
  175.                        open_auxwin();
  176.                     break;
  177.  
  178.                 case ButtonPress:
  179.                    if( event.xbutton.button == Button3)
  180.                    {
  181.                          xup1 = event.xmotion.x;
  182.                          yup1 = event.xmotion.y;
  183.                          box[0].x = xup1;
  184.                          box[0].y = yup1;
  185.                          box[4].x = xup1;
  186.                          box[4].y = yup1;
  187.                          myXor = TRUE;
  188.                          firsttime = TRUE;
  189.                    }
  190.                    if( event.xbutton.button == Button2)
  191.                    {
  192.                       reset_color();
  193.                       drawScene();
  194.                    }
  195.                    break;
  196.  
  197.                 case ButtonRelease:
  198.                    if( event.xbutton.button == Button3)
  199.                    {
  200.                       int xsz,ysz;
  201.  
  202.                       xup2 = event.xmotion.x;
  203.                       yup2 = event.xmotion.y;
  204.                       box[1].x = xup2;
  205.                       box[1].y = yup1;
  206.                       box[2].x = xup2;
  207.                       box[2].y = yup2;
  208.                       box[3].x = xup1;
  209.                       myXor = FALSE;
  210.                       xsz = abs(xup2-xup1);
  211.                       ysz = abs(yup2-yup1);
  212.  
  213.                      if( xsz>0 && ysz>0)
  214.                      {
  215.                         DrawXorPolyline(5,box);
  216.                         set_picking(box);
  217.                         drawScene();
  218.                      }
  219.                      clearbox();
  220.                    }
  221.                     break;
  222.  
  223.             /* "ConfigNotify" events are like "REDRAW" in terms of changes
  224.              *   to a window's size or position.
  225.              */
  226.                 case ConfigureNotify:                /* Resize GL manually */
  227.                     xsize = event.xconfigure.width;
  228.                     ysize = event.xconfigure.height;
  229.                     needToDraw = myConfigure = TRUE;
  230.                     break;
  231.  
  232.             /* Wait for "MotionNotify" events so the queue doesn't fill up
  233.              */
  234.                 case MotionNotify:
  235.                     if(myXor)
  236.                     {
  237.                       if(!firsttime)
  238.                          DrawXorPolyline(5,box);
  239.  
  240.                       xup2 = event.xmotion.x;
  241.                       yup2 = event.xmotion.y;
  242.                       box[1].x = xup2;
  243.                       box[1].y = yup1;
  244.                       box[2].x = xup2;
  245.                       box[2].y = yup2;
  246.                       box[3].x = xup1;
  247.                       box[3].y = yup2;
  248.                       DrawXorPolyline(5,box);
  249.                       firsttime = FALSE;
  250.                     }
  251.                     else
  252.                     {
  253.                       myButtPress = TRUE;
  254.                       xpos = event.xmotion.x;
  255.                       ypos = event.xmotion.y;
  256.                     }
  257.                     break;
  258.  
  259.             /* "ClientMessage" is generated if the WM itself is being
  260.              *  gunned down and sends an exit signal to any running prog.
  261.              */
  262.                 case ClientMessage:
  263.                     if (event.xclient.data.l[0] == del_atom)
  264.                         clean_exit();
  265.                     break;
  266.  
  267.             /* "KeyPress" events are those that would be generated before
  268.              *   whenever queueing up any KEYBD key via qdevice.
  269.              */
  270.                 case KeyPress:
  271.                    /* save out which unmodified key (i.e. the  key was
  272.                     *  not modified w/something like "Shift", "Ctrl",
  273.                     *  or "Alt") got pressed for use below.
  274.                     */
  275.                     XLookupString((XKeyEvent *)&event, buf, 4, &keysym, 0);
  276.                     myKeyPress = TRUE;
  277.                     break;
  278.  
  279.               }  /* end switch (event.type) */
  280.  
  281.  
  282.         } while (XPending(dpy));   /* end "do { } while".
  283.                                     * XPending() is like qtest()--it only
  284.                                     * tells you if there're any events
  285.                                     * presently in the queue.  it does not
  286.                                     * disturb queue's contents in any way.
  287.                                     */
  288.  
  289.     /* On an "Expose" event, redraw the affected pop'd or de-iconized window
  290.      */
  291.         if (myExpose) {
  292.             resize_buffer();
  293.             myExpose = FALSE;               /* reset flag--queue now empty */
  294.         }
  295.  
  296.     /* On a "ConfigureNotify" event, the GL window has either been moved or
  297.      *  resized.  Respond accordingly and then redraw its contents.
  298.      */
  299.         if (myConfigure) {
  300.             oxpos = xpos;
  301.             oypos = ypos;
  302.             resize_buffer();
  303.             myConfigure = FALSE;            /* reset flag--queue now empty */
  304.         }
  305.  
  306.         if (needToDraw) {
  307.             drawScene();
  308.             needToDraw = FALSE;
  309.         }
  310.  
  311.         /* On a keypress of Esc key, exit program.
  312.          */
  313.         if (myKeyPress) {
  314.             if (keysym == XK_Escape)
  315.                 clean_exit();
  316.         }
  317.  
  318.         if (myButtPress) {
  319.             orient();
  320.             drawScene();
  321.             myButtPress = FALSE;
  322.         }
  323.     }      /* end while(1) */
  324.  
  325. }      /* end main */
  326.  
  327.  
  328. static int attributeOverlay[] = { GLX_BUFFER_SIZE, 2,
  329.                                   GLX_LEVEL, 1,
  330.                                   GLX_GREEN_SIZE, 1,
  331.                                   None };
  332.  
  333. void open_auxwin()
  334. {
  335.     XSetWindowAttributes swa;
  336.     XVisualInfo *vi_o;
  337.     Colormap cmap_o;
  338.     Window root;
  339.     unsigned int width,height,border,depth;
  340.     int xorig,yorig;
  341.     int status;
  342.  
  343.       XGetGeometry(dpy,glwin, &root, &xorig, &yorig, &width, &height, &border,
  344. &depth);
  345.       vi_o = glXChooseVisual(dpy, DefaultScreen(dpy), attributeOverlay);
  346.       if (vi_o == NULL) {
  347.         printf("Unable to obtain Overlay Buffered VISUAL(????)\n");
  348.         exit(0);
  349.        }
  350.       cmap_o = XCreateColormap(dpy, RootWindow(dpy, vi_o->screen),
  351.                            vi_o->visual, AllocNone);
  352.  
  353.       status = XAllocNamedColor(dpy,cmap_o,"green",&green_pixel,&green_exact);
  354.       if(status == 0) {
  355.          printf("could not allocate green pixel\n");
  356.       }
  357.  
  358.       swa.colormap = cmap_o;
  359.       swa.border_pixel = green_pixel.pixel;
  360.       swa.border_pixel = BlackPixel(dpy,DefaultScreen(dpy));
  361.             /* express interest in events */;
  362.       swa.event_mask = StructureNotifyMask  | ButtonPressMask | ExposureMask |
  363.        Button1MotionMask | KeyPressMask | ButtonReleaseMask |
  364. Button3MotionMask;
  365.  
  366.       o_win = XCreateWindow(dpy, glwin, 0, 0, width, height, 0, vi_o->depth,
  367.                           InputOutput, vi_o->visual, CWBorderPixel|CWColormap,
  368. &swa);
  369.       XSetWMColormapWindows(dpy, glwin, &o_win, 1);
  370.  
  371.       XMapWindow(dpy, o_win);
  372.       back = BlackPixel(dpy,DefaultScreen(dpy));
  373.       fore = green_pixel.pixel;
  374.       
  375.     values.background=0;
  376.     values.foreground = fore;
  377.     values.function = GXxor;
  378.     valuemask =  GCFunction | GCBackground | GCForeground;
  379.     mygc = XCreateGC(dpy,o_win,valuemask,&values);
  380.  
  381. }
  382. static int attributeList[] = { GLX_RGBA,
  383.                    GLX_DEPTH_SIZE, 16,
  384.                                GLX_DOUBLEBUFFER,
  385.                                None };
  386.  
  387. static int attributeList2[] = { GLX_RGBA,
  388.                    GLX_DEPTH_SIZE, 16,
  389.                                GLX_DOUBLEBUFFER,
  390.                                None };
  391.  
  392.  
  393. static Bool WaitForNotify(Display *d, XEvent *e, char *arg) {
  394.     return (e->type == MapNotify) && (e->xmap.window == (Window)arg);
  395. }
  396.  
  397. XSizeHints Winhints;                          /* used to fix window size */
  398.  
  399.  
  400. /*  openwindow -
  401.  *     establish connection to X server, get screen info, specify the
  402.  *     attributes we want the WM to try to provide, and create the GL window
  403.  */
  404. static void openwindow(char *progname) {
  405.  
  406.     XVisualInfo *vi;
  407.     Colormap cmap;
  408.     XSizeHints Winhints;                          /* used to fix window size */
  409.     XSetWindowAttributes swa;
  410.     int scrnnum;                               /* X screen number            */
  411.     int xorig, yorig;                          /* window (upper-left) origin */
  412.     long scrnheight;
  413.  
  414.  
  415.    /* define window initial size */
  416.     xorig = 50;  yorig = 40;
  417.     xsize = 600; ysize = 600;
  418.     scrnaspect = xsize / (double) ysize;
  419.  
  420.    /* Connect to the X server and get screen info */
  421.     if ((dpy = XOpenDisplay(NULL)) == NULL) {
  422.         fprintf(stderr, "%s: cannot connect to X server %s\n",
  423.                                  progname, XDisplayName(NULL));
  424.         exit(1);
  425.     }
  426.  
  427.     scrnnum = DefaultScreen(dpy);
  428.     scrnheight = DisplayHeight(dpy, scrnnum);
  429.  
  430.         /* get an appropriate visual */
  431.     vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList);
  432.     if (vi == NULL) {
  433.     fprintf(stderr, "Unable to obtain visual Doublebuffered visual\n");
  434.     vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList2);
  435.     }
  436.     if (vi == NULL) {
  437.         printf("Unable to obtain Singlebuffered VISUAL(????)\n");
  438.         exit(0);
  439.     }
  440.     /* create a GLX context */
  441.     cx = glXCreateContext(dpy, vi, None, GL_TRUE);
  442.  
  443.     /* create a colormap */
  444.     cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
  445.                            vi->visual, AllocNone);
  446.  
  447.     /* create a window */
  448.     swa.colormap = cmap;
  449.     swa.border_pixel = 0;
  450.             /* express interest in events */;
  451.     swa.event_mask = StructureNotifyMask  | ButtonPressMask | ExposureMask |
  452.      Button1MotionMask | KeyPressMask | ButtonReleaseMask | Button3MotionMask;
  453.     glwin = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
  454.                           xorig, yorig, xsize, ysize,
  455.                           0, vi->depth, InputOutput, vi->visual,
  456.                           CWBorderPixel|CWColormap|CWEventMask, &swa);
  457.     XMapWindow(dpy, glwin);
  458.  
  459.  
  460.     /*  XGetWindowAttributes(dpy,glwin,&winattri); */
  461. /*    XGetWindowAttributes(dpy,o_win,&winattri); */
  462.  
  463.     XIfEvent(dpy, &event, WaitForNotify, (char*)glwin);
  464.  
  465.     /* connect the context to the window */
  466.     glXMakeCurrent(dpy, glwin, cx);
  467.  
  468. /*    printf("Back = %d fore = %d\n",back,fore);  */
  469.  
  470.     if (!(glwin)) {
  471.         fprintf(stderr,"%s: couldn't create \"parent\" X window\n",progname);
  472.         exit(1);
  473.     }
  474.  
  475.  
  476.    /* define string that will show up in the window title bar (and icon) */
  477.     XStoreName(dpy, glwin, "Picking using overlay ");
  478.  
  479.    /* specify the values for the Window Size Hints we want to enforce:  this
  480.     *  window's aspect ratio needs to stay at 1:1, constrain min and max
  481.     *  window size, and specify the initial size of the window.
  482.     */
  483.     Winhints.width  = xsize;          /* specify desired x/y size of window */
  484.     Winhints.height = ysize;
  485.     Winhints.min_width = xorig;                       /* define min and max */
  486.     Winhints.max_width = scrnheight-1;                /* width and height   */
  487.     Winhints.min_height = yorig;
  488.     Winhints.max_height = scrnheight-1;
  489.     Winhints.min_aspect.x = xsize;    /* keep aspect to a xsize:ysize ratio */
  490.     Winhints.max_aspect.x = xsize;
  491.     Winhints.min_aspect.y = ysize;
  492.     Winhints.max_aspect.y = ysize;
  493.     Winhints.flags = USSize|PMaxSize|PMinSize|PAspect;           /* set the */
  494.     XSetNormalHints(dpy, glwin, &Winhints);      /* corresponding flags */
  495.  
  496.    /* express interest in WM killing this app */
  497.     if ((del_atom = XInternAtom(dpy, "WM_DELETE_WINDOW", True)) != None)
  498.         XSetWMProtocols(dpy, glwin, &del_atom, 1);
  499.  
  500.     return ;
  501. }
  502.  
  503. /*  window has been moved or resized so update viewport & CTM stuff.
  504.  */
  505. static void resize_buffer() {
  506.  
  507.     XSync(dpy, False);  /* STILL NEED THIS????? *//* Need before GL reshape */
  508.     scrnaspect = xsize / (double) ysize;
  509.     glViewport(0, 0, xsize-1, ysize-1);
  510. }
  511.  
  512.  
  513.  
  514. /*  clean up before exiting
  515.  */
  516. static void clean_exit(void)
  517. {
  518.     XCloseDisplay(dpy);
  519.     exit(0);
  520. }
  521.  
  522.  
  523.  
  524. /* setup all necessary GL initialzation parameters.
  525.  */
  526. void initGL()
  527. {
  528.     glEnable(GL_DEPTH_TEST);
  529.     glClearColor(0.0, 0.0, 0.0, 0.0);
  530.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  531.     glMatrixMode(GL_PROJECTION);
  532.     glLoadIdentity();
  533.  
  534. /*    gluPerspective(400.0, scrnaspect, 30.0, 1000.0);   */
  535.  
  536.     glOrtho(-0.5, 0.5, -0.5, 0.5, -12.0, 12.0);
  537.     glMatrixMode(GL_MODELVIEW);
  538.  
  539. }
  540.  
  541.  
  542. void orient()
  543. {
  544.     float dx, dy;
  545.     glPushMatrix();
  546.  
  547.     dx = xpos-oxpos;
  548.     dy = oypos-ypos;
  549.     glLoadIdentity();
  550.     glRotatef((float) (0.03*(xpos-oxpos)), 1.0, 0.0, 0.0);
  551.     glRotatef((float) (0.03*(oypos-ypos)), 0.0, 1.0, 0.0);
  552.     glMultMatrixf(objmat);
  553.     glGetFloatv(GL_MODELVIEW_MATRIX, objmat);
  554.  
  555.     glPopMatrix();
  556. }
  557.  
  558.  
  559. void drawScene()
  560. {
  561.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  562.  
  563.     glPushMatrix();
  564.     glMultMatrixf(objmat);
  565.     drawPolys();
  566.     glPopMatrix();
  567.     glFlush ();
  568.     glXSwapBuffers(dpy, glwin);
  569.  
  570.  
  571. }
  572. void drawPolys()
  573. {
  574.   int i,j,k;
  575.   int id,col;
  576.  
  577.   col = 1;
  578.   glColor3f(0.8, 0.8, 0.8);
  579.  
  580.   em = elem;
  581.   for(i=0; i<no_elem; i++,em++)
  582.   {
  583.     if(picking)
  584.     {
  585.       id = i+101;
  586.       glPopName();
  587.       glPushName(id);
  588.     }
  589.     if(em->colr != col)
  590.     {
  591.        col = em->colr;
  592.        if(col == 2)
  593.          glColor3f(1.0, 0.0, 0.0);
  594.        else
  595.          glColor3f(0.8, 0.8, 0.8);
  596.     }
  597.     glBegin(GL_LINE_STRIP);
  598.      glVertex3fv(&em->xyz[0]);
  599.      glVertex3fv(&em->xyz[3]);
  600.      glVertex3fv(&em->xyz[6]);
  601.      glVertex3fv(&em->xyz[9]);
  602.      glVertex3fv(&em->xyz[0]);
  603.     glEnd();
  604.   }
  605.  
  606. }
  607. void DrawXorPolyline(int num, XPoint *points)
  608. {
  609.  
  610.           XDrawLines(dpy, o_win, mygc, points, num, CoordModeOrigin);
  611.       XFlush(dpy);
  612.  
  613.       return;
  614. }
  615. /* -------------------------------------------------------------------- */
  616. void gendata(int nx, int ny)
  617. {
  618.  
  619.    int i,j,k,count;
  620.    int i1,i2,jj,kk,id;
  621.    float dx,dy;
  622.    float x,y,z;
  623.    float xx,yy;
  624.    int nxny;
  625.    int memsize;
  626.  
  627.    no_grid = (nx+1)*(ny+1);
  628.    no_elem = nx*ny;
  629.  
  630.    memsize = no_elem*sizeof(Elem);
  631.    elem = (Elem *)malloc(memsize);
  632.    memsize = no_grid*sizeof(Grid);
  633.    grid = (Grid *)malloc(memsize);
  634.  
  635.    dx = 0.8/(float)nx;
  636.    dy = 0.8/(float)ny;
  637.  
  638. /*   Generate grids        */
  639.  
  640.    count = 0;
  641.  
  642.    z = 0.0;
  643.    gd = grid;
  644.  
  645.    y = -0.4;
  646.    for(j=0; j < ny+1; j++)
  647.    {
  648.      x = -0.40;
  649.      for(i=0; i < nx+1; i++)
  650.      {
  651.           gd->id = count+1;
  652.           gd->xyz[0] = x;
  653.           gd->xyz[1] = y;
  654.           gd->xyz[2] = z;
  655.           count++;
  656.           gd++;
  657.           x += dx;
  658.      }
  659.      y += dy;
  660.    }
  661.  
  662. /*   Generate elements      */
  663.  
  664.    count=0;
  665.    em = elem;
  666.    for(j=0; j < ny; j++)
  667.    {
  668.      jj = j*(nx+1);
  669.      for(i=0; i < nx; i++)
  670.      {
  671.         em->id = count+1;
  672.         em->type = 0;
  673.         em->nd = 4;
  674.  
  675.         i1 = jj + i;
  676.         i2 = i1 + 1;
  677.         em->conn[0] = i1;
  678.         em->conn[1] = i2;
  679.         em->conn[2] = i2+(nx+1);
  680.         em->conn[3] = i1+(nx+1);
  681.         em->colr = 1;               /* 1 for white color, later on change to
  682. something elese */
  683.         em++;
  684.         count++;
  685.      }
  686.    }
  687.  
  688.    em = elem;
  689.    for(i=0; i<no_elem; i++,em++)
  690.    {
  691.       xx = yy =0.0;
  692.       for(j=0; j<4; j++)
  693.       {
  694.         id = em->conn[j];
  695.         xx += (grid+id)->xyz[0];
  696.         yy += (grid+id)->xyz[1];
  697.       }
  698.       xx = xx*0.25;
  699.       yy = yy*0.25;
  700.  
  701.       for(j=0,k=0; j<4; j++,k+=3)
  702.       {
  703.         id = em->conn[j];
  704.         x = (grid+id)->xyz[0];
  705.         y = (grid+id)->xyz[1];
  706.         z = (grid+id)->xyz[2];
  707.         dx = (xx -x)*0.3 ;
  708.         dy = (yy -y)*0.3 ;
  709.  
  710.         em->xyz[k]   = x + dx;
  711.         em->xyz[k+1] = y + dy;
  712.         em->xyz[k+2] = z;
  713.       }
  714.   }
  715.  
  716. /*   write data out to file    */
  717.  
  718. /*
  719.    printf("GRID data\n");
  720.  
  721.    gd = grid;
  722.    for(i=0 ;i< no_grid; i++)
  723.    {
  724.      printf("%6d %15.4f %15.4f %15.4f\n",
  725.          gd->id, gd->xyz[0], gd->xyz[1], gd->xyz[2]);
  726.      gd++;
  727.    }
  728.    printf("ELEMENT data\n");
  729.    em = elem;
  730.    for(i=0; i<no_elem; i++)
  731.    {
  732.      printf("%6d %6d %6d %6d %6d %6d %6d %6d %6d\n",
  733.        em->id, em->conn[0], em->conn[1], em->conn[2], em->conn[3]);
  734.      em++;
  735.    }
  736. */
  737. }
  738. void reset_color()
  739. {
  740.   int i,j;
  741.   em = elem;
  742.   for(i=0; i<no_elem; i++,em++)
  743.      em->colr = 1;
  744.   for(i=0; i<16; i++)
  745.       objmat[i] = 0.0;
  746.  
  747.   objmat[0] = 1.0;
  748.   objmat[5] = 1.0;
  749.   objmat[10] = 1.0;
  750.   objmat[15] = 1.0;
  751.  
  752.     values.background=0;
  753.     values.foreground = 0;
  754.     values.function = GXcopy;
  755.     valuemask =  GCFunction | GCBackground | GCForeground;
  756.     mygc = XCreateGC(dpy,o_win,valuemask,&values);
  757.   
  758.     XFillRectangle(dpy,o_win,mygc,0,0,xsize,ysize);
  759.  
  760.     values.background=0;
  761.     values.foreground = fore;
  762.     values.function = GXxor;
  763.     valuemask =  GCFunction | GCBackground | GCForeground;
  764.     mygc = XCreateGC(dpy,o_win,valuemask,&values);
  765.  
  766. }
  767. void set_picking(XPoint *box)
  768. {
  769.  
  770.   int hits,i,j,items,indx;
  771.   int z1,z2,id;
  772.   float x1,x2,y1,y2;
  773.  
  774.      picking = 1;
  775.       glSelectBuffer(pick_buffer_size, pick_buffer);
  776.       glRenderMode(GL_SELECT);
  777.       glInitNames();
  778.       glLoadName(0);
  779.  
  780.    x1 = (float)box[0].x/xsize - 0.5;
  781.    x2 = (float)box[1].x/xsize - 0.5;
  782.    y1 = (float)(ysize-box[0].y)/ysize - 0.5;
  783.    y2 = (float)(ysize-box[2].y)/ysize - 0.5;
  784.  
  785.    glMatrixMode(GL_PROJECTION);
  786.    glLoadIdentity();
  787.    glOrtho(x1,x2, y1,y2, -12.0, 12.0);
  788.    glMatrixMode(GL_MODELVIEW);
  789.  
  790.    drawScene();
  791.    picking = 0;
  792.  
  793.    reset_color();
  794.    hits = glRenderMode(GL_RENDER);
  795.    indx = 0;
  796.    for(i=0; i<hits; i++)
  797.    {
  798.      items = pick_buffer[indx++];
  799.      z1 = pick_buffer[indx++];
  800.      z2 = pick_buffer[indx++];
  801.      for(j=0; j<items; j++)
  802.      {
  803.         id = pick_buffer[indx++] - 101;
  804.         (elem+id)->colr = 2;
  805.      }
  806.    }
  807.    glMatrixMode(GL_PROJECTION);
  808.    glLoadIdentity();
  809.    glOrtho(-0.5, 0.5, -0.5, 0.5, -12.0, 12.0);
  810.    glMatrixMode(GL_MODELVIEW);
  811.    drawScene();
  812.  
  813. }
  814. void clearbox()
  815. {
  816.     int i;
  817.     for(i=0; i<5; i++)
  818.     {
  819.        box[i].x = 0;
  820.        box[i].y = 0;
  821.     }
  822. }
  823.